import mongoose from 'mongoose';
import OrganizationPermission, { IOrganizationPermission, IOrganizationPermissionDocument } from '../models/organizationPermission';

/**
 * 组织权限关联数据访问对象
 * 提供组织权限关联相关的数据库操作方法
 */
export class OrganizationPermissionDAO {
  /**
   * 创建新的组织权限关联
   * @param organizationPermissionData 组织权限关联数据
   * @returns 创建的组织权限关联文档
   */
  async create(organizationPermissionData: Partial<IOrganizationPermission>): Promise<IOrganizationPermissionDocument> {
    try {
      const organizationPermission = new OrganizationPermission(organizationPermissionData);
      return await organizationPermission.save();
    } catch (error: any) {
      if (error.code === 11000) {
        // 处理唯一性约束错误
        throw new Error('组织权限分配已存在');
      }
      throw error;
    }
  }

  /**
   * 根据ID查找组织权限关联
   * @param id 组织权限关联ID
   * @returns 组织权限关联文档或null
   */
  async findById(id: mongoose.Types.ObjectId | string): Promise<IOrganizationPermissionDocument | null> {
    try {
      if (!id) {
        throw new Error('组织权限ID不能为空');
      }
      
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('无效的组织权限ID');
      }
      
      return await OrganizationPermission.findById(id)
        .populate('permissionId')
        .populate('systemId')
        .populate('assignedBy')
        .populate('parentPermissionId');
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据组织ID查找权限关联
   * @param organizationId 组织ID
   * @param organizationType 组织类型
   * @param systemId 系统ID（可选）
   * @returns 组织权限关联列表
   */
  async findByOrganizationId(
    organizationId: mongoose.Types.ObjectId | string,
    organizationType?: 'team' | 'department' | 'group',
    systemId?: mongoose.Types.ObjectId | string
  ): Promise<IOrganizationPermissionDocument[]> {
    try {
      if (!organizationId) {
        throw new Error('组织ID不能为空');
      }
      
      if (!mongoose.Types.ObjectId.isValid(organizationId)) {
        throw new Error('无效的组织ID');
      }
      
      return await OrganizationPermission.findByOrganizationId(
        new mongoose.Types.ObjectId(organizationId),
        organizationType,
        systemId ? new mongoose.Types.ObjectId(systemId) : undefined
      );
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据权限ID查找组织关联
   * @param permissionId 权限ID
   * @param systemId 系统ID（可选）
   * @returns 拥有该权限的组织列表
   */
  async findByPermissionId(
    permissionId: mongoose.Types.ObjectId | string,
    systemId?: mongoose.Types.ObjectId | string
  ): Promise<IOrganizationPermissionDocument[]> {
    try {
      if (!permissionId) {
        throw new Error('权限ID不能为空');
      }
      
      if (!mongoose.Types.ObjectId.isValid(permissionId)) {
        throw new Error('无效的权限ID');
      }
      
      return await OrganizationPermission.findByPermissionId(
        new mongoose.Types.ObjectId(permissionId),
        systemId ? new mongoose.Types.ObjectId(systemId) : undefined
      );
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据系统ID查找组织权限关联
   * @param systemId 系统ID
   * @returns 系统下的组织权限关联列表
   */
  async findBySystemId(systemId: mongoose.Types.ObjectId | string): Promise<IOrganizationPermissionDocument[]> {
    try {
      if (!systemId) {
        throw new Error('系统ID不能为空');
      }
      
      if (!mongoose.Types.ObjectId.isValid(systemId)) {
        throw new Error('无效的系统ID');
      }
      
      return await OrganizationPermission.findBySystemId(new mongoose.Types.ObjectId(systemId));
    } catch (error) {
      throw error;
    }
  }

  /**
   * 检查组织是否拥有指定权限
   * @param organizationId 组织ID
   * @param organizationType 组织类型
   * @param permissionId 权限ID
   * @param systemId 系统ID（可选）
   * @returns 是否拥有权限
   */
  async hasPermission(
    organizationId: mongoose.Types.ObjectId | string,
    organizationType: 'team' | 'department' | 'group',
    permissionId: mongoose.Types.ObjectId | string,
    systemId?: mongoose.Types.ObjectId | string
  ): Promise<boolean> {
    try {
      if (!organizationId) {
        throw new Error('组织ID不能为空');
      }
      
      if (!organizationType) {
        throw new Error('组织类型不能为空');
      }
      
      if (!permissionId) {
        throw new Error('权限ID不能为空');
      }
      
      if (!mongoose.Types.ObjectId.isValid(organizationId)) {
        throw new Error('无效的组织ID');
      }
      
      if (!mongoose.Types.ObjectId.isValid(permissionId)) {
        throw new Error('无效的权限ID');
      }
      
      return await OrganizationPermission.hasPermission(
        new mongoose.Types.ObjectId(organizationId),
        organizationType,
        new mongoose.Types.ObjectId(permissionId),
        systemId ? new mongoose.Types.ObjectId(systemId) : undefined
      );
    } catch (error) {
      throw error;
    }
  }

  /**
   * 批量分配权限给组织
   * @param organizationId 组织ID
   * @param organizationType 组织类型
   * @param permissionIds 权限ID列表
   * @param assignedBy 分配者ID
   * @param systemId 系统ID（可选）
   * @param options 分配选项
   * @returns 分配结果
   */
  async batchAssign(
    organizationId: mongoose.Types.ObjectId | string,
    organizationType: 'team' | 'department' | 'group',
    permissionIds: (mongoose.Types.ObjectId | string)[],
    assignedBy: mongoose.Types.ObjectId | string,
    systemId?: mongoose.Types.ObjectId | string,
    options?: {
      expiresAt?: Date;
      inherited?: boolean;
      source?: 'direct' | 'inherited';
      parentPermissionId?: mongoose.Types.ObjectId | string;
    }
  ): Promise<{
    success: IOrganizationPermissionDocument[];
    failed: { permissionId: mongoose.Types.ObjectId; error: string }[];
  }> {
    try {
      if (!organizationId) {
        throw new Error('组织ID不能为空');
      }
      
      if (!organizationType) {
        throw new Error('组织类型不能为空');
      }
      
      if (!permissionIds || permissionIds.length === 0) {
        return { success: [], failed: [] };
      }
      
      if (!assignedBy) {
        throw new Error('分配者ID不能为空');
      }
      
      if (!mongoose.Types.ObjectId.isValid(organizationId)) {
        throw new Error('无效的组织ID');
      }
      
      if (!mongoose.Types.ObjectId.isValid(assignedBy)) {
        throw new Error('无效的分配者ID');
      }
      
      const validPermissionIds = permissionIds.map(id => {
        if (!mongoose.Types.ObjectId.isValid(id)) {
          throw new Error(`无效的权限ID: ${id}`);
        }
        return new mongoose.Types.ObjectId(id);
      });
      
      const batchOptions = {
        ...options,
        parentPermissionId: options?.parentPermissionId ? 
          new mongoose.Types.ObjectId(options.parentPermissionId) : undefined
      };
      
      return await OrganizationPermission.batchAssign(
        new mongoose.Types.ObjectId(organizationId),
        organizationType,
        validPermissionIds,
        new mongoose.Types.ObjectId(assignedBy),
        systemId ? new mongoose.Types.ObjectId(systemId) : undefined,
        batchOptions
      );
    } catch (error) {
      throw error;
    }
  }

  /**
   * 批量撤销组织权限
   * @param organizationId 组织ID
   * @param organizationType 组织类型
   * @param permissionIds 权限ID列表（可选，为空则撤销所有权限）
   * @param systemId 系统ID（可选）
   * @returns 撤销的权限数量
   */
  async batchRevoke(
    organizationId: mongoose.Types.ObjectId | string,
    organizationType: 'team' | 'department' | 'group',
    permissionIds?: (mongoose.Types.ObjectId | string)[],
    systemId?: mongoose.Types.ObjectId | string
  ): Promise<number> {
    try {
      if (!organizationId) {
        throw new Error('组织ID不能为空');
      }
      
      if (!organizationType) {
        throw new Error('组织类型不能为空');
      }
      
      if (!mongoose.Types.ObjectId.isValid(organizationId)) {
        throw new Error('无效的组织ID');
      }
      
      let validPermissionIds: mongoose.Types.ObjectId[] | undefined;
      
      if (permissionIds && permissionIds.length > 0) {
        validPermissionIds = permissionIds.map(id => {
          if (!mongoose.Types.ObjectId.isValid(id)) {
            throw new Error(`无效的权限ID: ${id}`);
          }
          return new mongoose.Types.ObjectId(id);
        });
      }
      
      return await OrganizationPermission.batchRevoke(
        new mongoose.Types.ObjectId(organizationId),
        organizationType,
        validPermissionIds,
        systemId ? new mongoose.Types.ObjectId(systemId) : undefined
      );
    } catch (error) {
      throw error;
    }
  }

  /**
   * 删除组织权限关联（软删除）
   * @param id 组织权限关联ID
   * @returns 是否删除成功
   */
  async delete(id: mongoose.Types.ObjectId | string): Promise<boolean> {
    try {
      if (!id) {
        throw new Error('组织权限ID不能为空');
      }
      
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('无效的组织权限ID');
      }
      
      const result = await OrganizationPermission.findByIdAndUpdate(
        id,
        { status: 0 },
        { new: true }
      );
      
      return result !== null;
    } catch (error) {
      throw error;
    }
  }

  /**
   * 硬删除组织权限关联
   * @param id 组织权限关联ID
   * @returns 是否删除成功
   */
  async hardDelete(id: mongoose.Types.ObjectId | string): Promise<boolean> {
    try {
      if (!id) {
        throw new Error('组织权限ID不能为空');
      }
      
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('无效的组织权限ID');
      }
      
      const result = await OrganizationPermission.findByIdAndDelete(id);
      return result !== null;
    } catch (error) {
      throw error;
    }
  }

  /**
   * 更新组织权限关联
   * @param id 组织权限关联ID
   * @param updateData 更新数据
   * @returns 更新后的组织权限关联文档
   */
  async update(
    id: mongoose.Types.ObjectId | string,
    updateData: Partial<IOrganizationPermission>
  ): Promise<IOrganizationPermissionDocument | null> {
    try {
      if (!id) {
        throw new Error('组织权限ID不能为空');
      }
      
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('无效的组织权限ID');
      }
      
      // 过滤掉不允许更新的字段
      const allowedFields = ['status', 'expiresAt', 'inherited', 'source'];
      const filteredUpdateData: any = {};
      
      for (const [key, value] of Object.entries(updateData)) {
        if (allowedFields.includes(key)) {
          filteredUpdateData[key] = value;
        }
      }
      
      return await OrganizationPermission.findByIdAndUpdate(
        id,
        filteredUpdateData,
        { new: true, runValidators: true }
      ).populate('permissionId')
       .populate('systemId')
       .populate('assignedBy')
       .populate('parentPermissionId');
    } catch (error) {
      throw error;
    }
  }

  /**
   * 获取组织在系统中的权限
   * @param organizationId 组织ID
   * @param organizationType 组织类型
   * @param systemId 系统ID
   * @param includeInherited 是否包含继承权限
   * @returns 组织权限列表
   */
  async getOrganizationPermissionsInSystem(
    organizationId: mongoose.Types.ObjectId | string,
    organizationType: 'team' | 'department' | 'group',
    systemId: mongoose.Types.ObjectId | string,
    includeInherited: boolean = true
  ): Promise<IOrganizationPermissionDocument[]> {
    try {
      if (!organizationId) {
        throw new Error('组织ID不能为空');
      }
      
      if (!organizationType) {
        throw new Error('组织类型不能为空');
      }
      
      if (!systemId) {
        throw new Error('系统ID不能为空');
      }
      
      if (!mongoose.Types.ObjectId.isValid(organizationId)) {
        throw new Error('无效的组织ID');
      }
      
      if (!mongoose.Types.ObjectId.isValid(systemId)) {
        throw new Error('无效的系统ID');
      }
      
      return await OrganizationPermission.getOrganizationPermissionsInSystem(
        new mongoose.Types.ObjectId(organizationId),
        organizationType,
        new mongoose.Types.ObjectId(systemId),
        includeInherited
      );
    } catch (error) {
      throw error;
    }
  }

  /**
   * 同步组织权限
   * @param organizationId 组织ID
   * @param organizationType 组织类型
   * @param permissionIds 权限ID列表
   * @param assignedBy 分配者ID
   * @param systemId 系统ID（可选）
   * @returns 同步结果
   */
  async syncOrganizationPermissions(
    organizationId: mongoose.Types.ObjectId | string,
    organizationType: 'team' | 'department' | 'group',
    permissionIds: (mongoose.Types.ObjectId | string)[],
    assignedBy: mongoose.Types.ObjectId | string,
    systemId?: mongoose.Types.ObjectId | string
  ): Promise<{
    added: IOrganizationPermissionDocument[];
    removed: number;
  }> {
    try {
      if (!organizationId) {
        throw new Error('组织ID不能为空');
      }
      
      if (!organizationType) {
        throw new Error('组织类型不能为空');
      }
      
      if (!permissionIds) {
        throw new Error('权限ID列表不能为空');
      }
      
      if (!assignedBy) {
        throw new Error('分配者ID不能为空');
      }
      
      if (!mongoose.Types.ObjectId.isValid(organizationId)) {
        throw new Error('无效的组织ID');
      }
      
      if (!mongoose.Types.ObjectId.isValid(assignedBy)) {
        throw new Error('无效的分配者ID');
      }
      
      const validPermissionIds = permissionIds.map(id => {
        if (!mongoose.Types.ObjectId.isValid(id)) {
          throw new Error(`无效的权限ID: ${id}`);
        }
        return new mongoose.Types.ObjectId(id);
      });
      
      return await OrganizationPermission.syncOrganizationPermissions(
        new mongoose.Types.ObjectId(organizationId),
        organizationType,
        validPermissionIds,
        new mongoose.Types.ObjectId(assignedBy),
        systemId ? new mongoose.Types.ObjectId(systemId) : undefined
      );
    } catch (error) {
      throw error;
    }
  }

  /**
   * 从父级组织继承权限
   * @param childOrganizationId 子组织ID
   * @param childOrganizationType 子组织类型
   * @param parentOrganizationId 父组织ID
   * @param parentOrganizationType 父组织类型
   * @param assignedBy 分配者ID
   * @param systemId 系统ID（可选）
   * @returns 继承的权限列表
   */
  async inheritFromParent(
    childOrganizationId: mongoose.Types.ObjectId | string,
    childOrganizationType: 'team' | 'department' | 'group',
    parentOrganizationId: mongoose.Types.ObjectId | string,
    parentOrganizationType: 'team' | 'department' | 'group',
    assignedBy: mongoose.Types.ObjectId | string,
    systemId?: mongoose.Types.ObjectId | string
  ): Promise<IOrganizationPermissionDocument[]> {
    try {
      if (!childOrganizationId) {
        throw new Error('子组织ID不能为空');
      }
      
      if (!childOrganizationType) {
        throw new Error('子组织类型不能为空');
      }
      
      if (!parentOrganizationId) {
        throw new Error('父组织ID不能为空');
      }
      
      if (!parentOrganizationType) {
        throw new Error('父组织类型不能为空');
      }
      
      if (!assignedBy) {
        throw new Error('分配者ID不能为空');
      }
      
      if (!mongoose.Types.ObjectId.isValid(childOrganizationId)) {
        throw new Error('无效的子组织ID');
      }
      
      if (!mongoose.Types.ObjectId.isValid(parentOrganizationId)) {
        throw new Error('无效的父组织ID');
      }
      
      if (!mongoose.Types.ObjectId.isValid(assignedBy)) {
        throw new Error('无效的分配者ID');
      }
      
      return await OrganizationPermission.inheritFromParent(
        new mongoose.Types.ObjectId(childOrganizationId),
        childOrganizationType,
        new mongoose.Types.ObjectId(parentOrganizationId),
        parentOrganizationType,
        new mongoose.Types.ObjectId(assignedBy),
        systemId ? new mongoose.Types.ObjectId(systemId) : undefined
      );
    } catch (error) {
      throw error;
    }
  }

  /**
   * 获取权限的组织数量
   * @param permissionId 权限ID
   * @param systemId 系统ID（可选）
   * @param organizationType 组织类型（可选）
   * @returns 拥有该权限的组织数量
   */
  async getPermissionOrganizationCount(
    permissionId: mongoose.Types.ObjectId | string,
    systemId?: mongoose.Types.ObjectId | string,
    organizationType?: 'team' | 'department' | 'group'
  ): Promise<number> {
    try {
      if (!permissionId) {
        throw new Error('权限ID不能为空');
      }
      
      if (!mongoose.Types.ObjectId.isValid(permissionId)) {
        throw new Error('无效的权限ID');
      }
      
      return await OrganizationPermission.getPermissionOrganizationCount(
        new mongoose.Types.ObjectId(permissionId),
        systemId ? new mongoose.Types.ObjectId(systemId) : undefined,
        organizationType
      );
    } catch (error) {
      throw error;
    }
  }

  /**
   * 获取组织的权限数量
   * @param organizationId 组织ID
   * @param organizationType 组织类型
   * @param systemId 系统ID（可选）
   * @param includeInherited 是否包含继承权限
   * @returns 组织拥有的权限数量
   */
  async getOrganizationPermissionCount(
    organizationId: mongoose.Types.ObjectId | string,
    organizationType: 'team' | 'department' | 'group',
    systemId?: mongoose.Types.ObjectId | string,
    includeInherited: boolean = true
  ): Promise<number> {
    try {
      if (!organizationId) {
        throw new Error('组织ID不能为空');
      }
      
      if (!organizationType) {
        throw new Error('组织类型不能为空');
      }
      
      if (!mongoose.Types.ObjectId.isValid(organizationId)) {
        throw new Error('无效的组织ID');
      }
      
      return await OrganizationPermission.getOrganizationPermissionCount(
        new mongoose.Types.ObjectId(organizationId),
        organizationType,
        systemId ? new mongoose.Types.ObjectId(systemId) : undefined,
        includeInherited
      );
    } catch (error) {
      throw error;
    }
  }

  /**
   * 查询所有组织权限关联
   * @param criteria 查询条件
   * @param options 查询选项
   * @returns 分页的组织权限关联列表
   */
  async findAll(
    criteria: {
      organizationId?: mongoose.Types.ObjectId | string;
      organizationType?: 'team' | 'department' | 'group';
      permissionId?: mongoose.Types.ObjectId | string;
      systemId?: mongoose.Types.ObjectId | string;
      status?: number;
      source?: 'direct' | 'inherited';
    } = {},
    options: {
      page?: number;
      limit?: number;
      sort?: string;
      select?: string;
    } = {}
  ): Promise<{ organizationPermissions: IOrganizationPermissionDocument[]; total: number; page: number; totalPages: number }> {
    try {
      const {
        organizationId,
        organizationType,
        permissionId,
        systemId,
        status = 1,
        source
      } = criteria;
      
      const {
        page = 1,
        limit = 10,
        sort = '-createdAt',
        select
      } = options;
      
      // 构建查询条件
      const query: any = {};
      
      if (status !== undefined) {
        if (![0, 1].includes(status)) {
          throw new Error('无效的状态值');
        }
        query.status = status;
      }
      
      if (organizationId) {
        if (!mongoose.Types.ObjectId.isValid(organizationId)) {
          throw new Error('无效的组织ID');
        }
        query.organizationId = new mongoose.Types.ObjectId(organizationId);
      }
      
      if (organizationType) {
        query.organizationType = organizationType;
      }
      
      if (permissionId) {
        if (!mongoose.Types.ObjectId.isValid(permissionId)) {
          throw new Error('无效的权限ID');
        }
        query.permissionId = new mongoose.Types.ObjectId(permissionId);
      }
      
      if (systemId) {
        if (!mongoose.Types.ObjectId.isValid(systemId)) {
          throw new Error('无效的系统ID');
        }
        query.systemId = new mongoose.Types.ObjectId(systemId);
      }
      
      if (source) {
        query.source = source;
      }
      
      // 计算跳过的文档数
      const skip = (page - 1) * limit;
      
      // 执行查询
      let queryBuilder = OrganizationPermission.find(query)
        .populate('permissionId')
        .populate('systemId')
        .populate('assignedBy')
        .populate('parentPermissionId')
        .sort(sort)
        .skip(skip)
        .limit(limit);
      
      if (select) {
        queryBuilder = queryBuilder.select(select);
      }
      
      const [organizationPermissions, total] = await Promise.all([
        queryBuilder,
        OrganizationPermission.countDocuments(query)
      ]);
      
      const totalPages = Math.ceil(total / limit);
      
      return {
        organizationPermissions,
        total,
        page,
        totalPages
      };
    } catch (error) {
      throw error;
    }
  }

  /**
   * 清理过期权限
   * @param systemId 系统ID（可选）
   * @returns 清理的权限数量
   */
  async cleanupExpiredPermissions(systemId?: mongoose.Types.ObjectId | string): Promise<number> {
    try {
      return await OrganizationPermission.cleanupExpiredPermissions(
        systemId ? new mongoose.Types.ObjectId(systemId) : undefined
      );
    } catch (error) {
      throw error;
    }
  }

  /**
   * 获取即将过期的权限
   * @param days 天数
   * @param systemId 系统ID（可选）
   * @returns 即将过期的权限列表
   */
  async getExpiringPermissions(
    days: number,
    systemId?: mongoose.Types.ObjectId | string
  ): Promise<IOrganizationPermissionDocument[]> {
    try {
      if (!days || days <= 0) {
        throw new Error('天数必须大于0');
      }
      
      return await OrganizationPermission.getExpiringPermissions(
        days,
        systemId ? new mongoose.Types.ObjectId(systemId) : undefined
      );
    } catch (error) {
      throw error;
    }
  }
}

export default OrganizationPermissionDAO;